package com.gzhryc.shared_device.oem.code.device;

import com.gzhryc.common.StringTools;
import com.gzhryc.common.json.JsonTools;
import com.gzhryc.common.logging.Logger;
import com.gzhryc.common.redis.RedisTools;
import com.gzhryc.shared_device.base.models.SlotLock;
import com.gzhryc.shared_device.cdcz.code.ICDCZCacheManager;
import com.gzhryc.shared_device.cdcz.code.dao.db.ChargeSocket;
import com.gzhryc.shared_device.cdcz.code.dao.db.ChargeSocketSlot;
import com.gzhryc.shared_device.oem.code.RedisDBConstants;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.ScanParams;
import redis.clients.jedis.ScanResult;

import java.util.*;

public class CDCZCacheManager implements ICDCZCacheManager {

    static Logger log = Logger.getLogger(CDCZCacheManager.class);

    static CDCZCacheManager me;

    public static CDCZCacheManager self() {
        if (me == null) {
            me = new CDCZCacheManager();
        }
        return me;
    }

    Long times = 30L; //30秒

    @Override
    public ChargeSocket getChargeSocket(String deviceSn) {
        if (StringTools.isNotBlank(deviceSn)) {
            String json = RedisTools.get().get(RedisDBConstants.CDCZ_DEVICE_DB, deviceSn);
            if (JsonTools.isJsonStr(json)) {
                return JsonTools.fromJson(json, ChargeSocket.class);
            }
        }
        return null;
    }

    @Override
    public void saveChargeSocket(ChargeSocket chargeSocket) {
        if (chargeSocket != null && StringTools.isNotBlank(chargeSocket.getDeviceSn())) {
            RedisTools.get().set(RedisDBConstants.CDCZ_DEVICE_DB, chargeSocket.getDeviceSn(), JsonTools.toJson(chargeSocket));
        }
    }

    @Override
    public void removeChargeSocket(String deviceSn) {
        if (StringTools.isNotBlank(deviceSn)) {
            RedisTools.get().delete(RedisDBConstants.CDCZ_DEVICE_DB, deviceSn);
            //删除所有卡槽信息
            removeChargeSocketSlot(deviceSn);
        }
    }

    @Override
    public ChargeSocketSlot getChargeSocketSlot(String deviceSn, Integer slotNum) {
        if (StringTools.isNotBlank(deviceSn) && slotNum != null) {
            String key = deviceSn + "_" + slotNum;
            String json = RedisTools.get().get(RedisDBConstants.CDCZ_DEVICE_SLOT_DB, key);
            if (JsonTools.isJsonStr(json)) {
                return JsonTools.fromJson(json, ChargeSocketSlot.class);
            }
        }
        return null;
    }

    public boolean lockCDCZSlot(String deviceSn, Integer slotNum) {
        if (StringTools.isNotBlank(deviceSn) && slotNum != null) {
            String key = deviceSn + "_" + slotNum;
            if (!RedisTools.get().exists(RedisDBConstants.CDCZ_DEVICE_SLOT_LOCK_DB, key)) {
                try {
                    String value = DateFormatUtils.format(new Date(), "yyyy-MM-dd HH:mm:ss");
                    return RedisTools.get().setnx(RedisDBConstants.CDCZ_DEVICE_SLOT_LOCK_DB, key, value, times);
                } catch (Exception e) {
                    log.error(e.getMessage(), e);
                }
            }
        }
        return false;
    }

    public boolean unlockCDCZSlot(String deviceSn, Integer slotNum) {
        if (StringTools.isNotBlank(deviceSn) && slotNum != null) {
            String key = deviceSn + "_" + slotNum;
            return RedisTools.get().delete(RedisDBConstants.CDCZ_DEVICE_SLOT_LOCK_DB, key);
        }
        return false;
    }

    public List<SlotLock> getChargeSocketSlotLock() {
        Jedis jedis = RedisTools.get().getJedis();
        if (jedis != null) {
            try {
                List<SlotLock> data = new ArrayList<>();
                jedis.select(RedisDBConstants.CDCZ_DEVICE_SLOT_LOCK_DB);
                String cursor = ScanParams.SCAN_POINTER_START;
                do {
                    ScanResult<String> result = jedis.scan(cursor);
                    if (result == null)
                        break;
                    cursor = result.getCursor();
                    if (result != null && result.getResult() != null) {
                        for (String key : result.getResult()) {
                            try {
                                String[] temp = key.split("_");
                                SlotLock slotLock = new SlotLock();
                                slotLock.setDeviceSn(temp[0]);
                                slotLock.setSlotNum(Integer.valueOf(temp[1]));
                                slotLock.setCreateDate(jedis.get(key));
                                data.add(slotLock);
                            } catch (Exception e) {
                                log.error(e.getMessage(), e);
                            }
                        }
                    }
                } while (!cursor.equals(ScanParams.SCAN_POINTER_START));
                return data;

            } catch (Exception e) {
                log.error(e.getMessage(), e);
            } finally {
                jedis.close();
            }
        }
        return null;
    }

    public List<ChargeSocketSlot> getChargeSocketSlot(String deviceSn) {
        if (StringTools.isNotBlank(deviceSn)) {
            Jedis jedis = RedisTools.get().getJedis();
            if (jedis != null) {
                try {
                    List<ChargeSocketSlot> socketSlotList = new ArrayList<>();
                    jedis.select(RedisDBConstants.CDCZ_DEVICE_SLOT_DB);
                    String cursor = ScanParams.SCAN_POINTER_START;
                    String trim = deviceSn + "_*";
                    ScanParams scanParams = new ScanParams();
                    scanParams.match(trim);// 匹配以 key* 为前缀的 key
                    do {
                        ScanResult<String> result = jedis.scan(cursor, scanParams);
                        if (result == null)
                            break;
                        cursor = result.getCursor();
                        if (result != null && result.getResult() != null) {
                            for (String key : result.getResult()) {
                                String obj = jedis.get(key);
                                if (StringUtils.isNoneBlank(obj)) {
                                    socketSlotList.add(JsonTools.fromJson(obj, ChargeSocketSlot.class));
                                }
                            }
                        }
                    } while (!cursor.equals(ScanParams.SCAN_POINTER_START));
                    return socketSlotList;

                } catch (Exception e) {
                    log.error(e.getMessage(), e);
                } finally {
                    jedis.close();
                }
            }
        }
        return null;
    }

    @Override
    public void saveChargeSocketSlot(ChargeSocketSlot chargeSocketSlot) {
        if (chargeSocketSlot != null && StringTools.isNotBlank(chargeSocketSlot.getDeviceSn()) && chargeSocketSlot.getSlotNum() != null) {
            String key = chargeSocketSlot.getDeviceSn() + "_" + chargeSocketSlot.getSlotNum();
            RedisTools.get().set(RedisDBConstants.CDCZ_DEVICE_SLOT_DB, key, JsonTools.toJson(chargeSocketSlot));
        }
    }

    @Override
    public void removeChargeSocketSlot(String deviceSn, Integer slotNum) {
        if (StringTools.isNotBlank(deviceSn) && slotNum != null) {
            String key = deviceSn + "_" + slotNum;
            RedisTools.get().delete(RedisDBConstants.CDCZ_DEVICE_SLOT_DB, key);
        }
    }

    @Override
    public void removeChargeSocketSlot(String deviceSn) {
        if (StringTools.isNotBlank(deviceSn)) {
            Jedis jedis = RedisTools.get().getJedis();
            if (jedis != null) {
                try {
                    jedis.select(RedisDBConstants.CDCZ_DEVICE_SLOT_DB);
                    Set<String> keys = jedis.keys(deviceSn + "_\\d+");
                    if (keys != null && keys.size() > 0) {
                        for (String key : keys) {
                            jedis.del(key);
                        }
                    }
                } catch (Exception e) {
                    log.error(e.getMessage(), e);
                } finally {
                    jedis.close();
                }
            }
        }
    }

    public List<ChargeSocket> findCDCZDevice() {
        Jedis jedis = RedisTools.get().getJedis();
        if (jedis != null) {
            try {
                List<ChargeSocket> deviceList = new ArrayList<>();
                jedis.select(RedisDBConstants.CDCZ_DEVICE_DB);
                String cursor = ScanParams.SCAN_POINTER_START;
                do {
                    ScanResult<String> result = jedis.scan(cursor);
                    if (result == null)
                        break;
                    cursor = result.getCursor();
                    if (result != null && result.getResult() != null) {
                        for (String key : result.getResult()) {
                            String obj = jedis.get(key);
                            if (StringUtils.isNoneBlank(obj)) {
                                deviceList.add(JsonTools.fromJson(obj, ChargeSocket.class));
                            }
                        }
                    }
                } while (!cursor.equals(ScanParams.SCAN_POINTER_START));
                return deviceList;
            } catch (Exception e) {
                log.error(e.getMessage(), e);
            } finally {
                jedis.close();
            }
        }
        return null;
    }
}
